/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including but not limited to the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to provide persons with access to the Software
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGE OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import React, { useEffect, useRef, useState, useContext, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import { RootState, AppDispatch } from '../../store';
import { addMusiclist } from '../../store/musicSlice';
import { PlayerContext } from '../../context/PlayerContext';
import repeatIcon from '../../assets/images/repeat.svg';
import leftIcon from '../../assets/images/left.svg';
import pauseIcon from '../../assets/images/pause.svg';
import playIcon from '../../assets/images/play.svg';
import forwardIcon from '../../assets/images/forward_end_fill.svg';
import noteListIcon from '../../assets/images/music_note_list.svg';
import sharePlayIcon from '../../assets/images/share_play.svg';
import bellIcon from '../../assets/images/bell.svg';
import arrowDownCircleIcon from '../../assets/images/arrow_down_circle.svg';
import dotIcon from '../../assets/images/dot.svg';
import { useInteraction } from '../../utils/useInteraction';

import './index.less';

interface MusicPlayerProps {
  deviceType?: string;
  isPlay?: string;
  musicId?: number;
  musicListNum?: number;
  onUpdateMusic?: (musicId: number) => void;
  onUpdateIsPlay?: (isPlay: string) => void;
}

const formatTime = (time: number): string => {
  const minutes = Math.floor(time / 60);
  const seconds = Math.floor(time % 60);
  return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
};

const MusicPlayer: React.FC<MusicPlayerProps> = ({
  deviceType = 'mobile',
  isPlay: propIsPlay = 'pause',
  musicId: propMusicId = 1,
  musicListNum = 50,
  onUpdateMusic,
  onUpdateIsPlay,
}) => {
  const navigate = useNavigate();
  const musicList = useSelector((state: RootState) => state.music.musicList);
  const { player } = useContext(PlayerContext);

  const [isPlay, setIsPlay] = useState<string>(propIsPlay);
  const musicId = useRef<number>(propMusicId);
  const [musicTime, setMusicTime] = useState<string>('00:00');
  const [musicPlayTime, setMusicPlayTime] = useState<string>('00:00');
  const [getWidth, setGetWidth] = useState<number>(0);
  const [getOffLeft, setgetOffLeft] = useState<number>(0);

  const scheduleRef = useRef<HTMLSpanElement>(null);
  const scheduleWidth = useRef<number>(0);
  const startX = useRef<number>(0);

  const progressRef = useInteraction({
    handlers: {
      onClick: (e: any) => handleClick(e),
      onScroll: (e: any) => handleScrollStart(e),

    },
    configs: {
      enableClick: true,
      enableScroll: true,
    },
  });

  // 初始化
  useEffect(() => {
    player.seekTo(0);
    const current = musicList.find((item) => item.id === Number(musicId.current));

    if (isPlay === 'play' && Number(musicId.current) === current?.id) {
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
    } else {
      player.seekTo(0);
      setIsPlay('pause');
    }
    const timer = setTimeout(() => {
      if (scheduleRef.current) {
        startX.current = scheduleRef.current.getBoundingClientRect().left;
        const style = window.getComputedStyle(scheduleRef.current);
        scheduleWidth.current = parseFloat(style.width);
      }
      setMusicTime(formatTime(player.getDuration()));
      if (player.getCurrentTime() > 0 && isPlay === 'pause') {
        const progressPercentage =
          (player.getCurrentTime() / player.getDuration()) * 100;
        setGetWidth(progressPercentage);
        setMusicPlayTime(formatTime(player.getCurrentTime()));
      }
    }, 100);

    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    // 键盘事件
    const keyIncident = (ev: KeyboardEvent): void => {
      ev.preventDefault();
      switch (ev.key) {
        case 'ArrowUp':
          previousTrack();
          break;
        case 'ArrowDown':
          theNextSong();
          break;
        case 'ArrowLeft':
          if (player.getCurrentTime() - 5 < 0) {
            player.seekTo(0);
            setMusicPlayTime(formatTime(0));
          } else {
            seek(-5);
          }
          break;
        case 'ArrowRight':
          if (player.getCurrentTime() + 5 > player.getDuration()) {
            player.seekTo(player.getDuration());
            setMusicPlayTime(formatTime(player.getDuration()));
          } else {
            seek(5);
          }
          break;
        case 'Enter':
          setIsPlay('play');
          player.play();
          onUpdateIsPlay && onUpdateIsPlay('play');
          break;
        case 'Escape':
          navigate(`/musicList?isPlay=${isPlay}&musicId=${musicId.current}`);
          break;
        case ' ':
          setIsPlay('pause');
          player.pause();
          onUpdateIsPlay && onUpdateIsPlay('pause');
          break;
      }
    };
    document.addEventListener('keydown', keyIncident);
    document.oncontextmenu = function (e): boolean {
      e.preventDefault();
      return false;
    };
    return () => {
      document.removeEventListener('keydown', keyIncident);
      document.oncontextmenu = null;
    };
    // eslint-disable-next-line
  }, []);

  // 进度条时间更新
  const handleTimeUpdate = (time: number, dur: number): void => {
    const progress = (time / dur) * 100;
    setGetWidth(progress);
    setMusicPlayTime(formatTime(time));
  };

  // 播放或暂停
  const playMusic = (value: string): void => {
    setIsPlay(value);
    if (value === 'pause') {
      player.pause();
    } else {
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
    }
    onUpdateIsPlay && onUpdateIsPlay(value);
  };

  // 拖拽、点击、长按等交互
  const handleClick = (e: any): void => {
    if (!scheduleRef.current) {
      return;
    }
    const rect = scheduleRef.current.getBoundingClientRect();
    const x = e.windowX - rect.left;
    const currentProgress = (x / rect.width) * 100;
    if (currentProgress > 0 && currentProgress <= 100) {
      const newTime = (currentProgress * player.getDuration()) / 100;
      setGetWidth(currentProgress);
      player.seekTo(newTime);
      setMusicPlayTime(formatTime(newTime));
    }
  };

  // 上一曲
  const previousTrack = (): void => {
    player.pause();
    updateMusic(-1);
  };

  // 下一曲
  const theNextSong = (): void => {
    player.pause();
    updateMusic(1);
  };

  // 切歌
  const updateMusic = (num: number): void => {
    const musicIndex = musicList.findIndex((item) => item.id === musicId.current);
    if (musicIndex === -1) {
      return; // 如果 musicId 未找到，直接返回
    }

    const newIndex = musicIndex + num;
    if (newIndex >= 0 && newIndex < musicList.length) {
      const nextMusic = musicList[newIndex];
      player.seekTo(0);
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
      setIsPlay('play');
      musicId.current = nextMusic.id;
      onUpdateIsPlay && onUpdateIsPlay('play');
      onUpdateMusic && onUpdateMusic(nextMusic.id);
    }
  };

  // 快进快退
  const seek = (num: number): void => {
    const newTime = player.getCurrentTime() + num;
    player.seekTo(newTime);
    setMusicPlayTime(formatTime(newTime));
  };

  const handleScrollStart = (e): void => {
    const currentProgress = ((e.windowX - Number(startX.current)) / Number(scheduleWidth.current)) * 100;
    if (currentProgress > 0 && currentProgress <= 100) {
      const newTime = (currentProgress * player.getDuration()) / 100;
      setGetWidth(currentProgress);

      player.seekTo(newTime);
      setMusicPlayTime(formatTime(newTime));
    }
  };

  const progressMemo = useMemo(() => {
    return (
      <div className='progress-container' ref={progressRef as any} >
        <div className='progress-track' ref={scheduleRef as any} >
          <div className='progress-buffered' style={{ width: getWidth + '%' }}></div>
          <div className='progress-fill' style={{ width: getOffLeft + '%' }}></div>
        </div>
        <div className='time'>
          <span className='current-time'>{musicPlayTime}</span>
          <span className='duration'>{musicTime}</span>
        </div>
      </div>
    );
  }, [getWidth, musicTime]);


  return (
    <div className='player'>
      <div className='time_schedule'>
        {progressMemo}
      </div>
      <div className='play_icon'>
        <img src={repeatIcon} alt='' />
        <img onClick={previousTrack} src={leftIcon} alt='' />
        {isPlay === 'play' ? (
          <img onClick={(): void => playMusic('pause')} src={pauseIcon} alt='' />
        ) : (
          <img onClick={(): void => playMusic('play')} src={playIcon} alt='' />
        )}
        <img onClick={theNextSong} src={forwardIcon} alt='' />
        <img src={noteListIcon} alt='' />
      </div>
      <div className='play_nav_icon'>
        <img src={sharePlayIcon} alt='' />
        <img src={bellIcon} alt='' />
        <img src={arrowDownCircleIcon} alt='' />
        <img src={dotIcon} alt='' />
      </div>
    </div>
  );
};

export default MusicPlayer;